package com.moo2u2.android.oaktononthego.locate;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import android.content.Context;
import android.graphics.Point;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.LayerDrawable;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.Display;
import android.view.LayoutInflater;
import android.view.View;
import android.view.WindowManager;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;

import com.google.android.maps.GeoPoint;
import com.google.android.maps.ItemizedOverlay;
import com.google.android.maps.MapView;
import com.google.android.maps.Projection;
import com.moo2u2.android.oaktononthego.R;

public class ColleagueOverlay extends ItemizedOverlay<ColleagueOverlayItem> {

    private ArrayList<ColleagueOverlayItem> colleagues = new ArrayList<ColleagueOverlayItem>();

    private final Context context;

    private LayoutInflater layoutInflator;

    private RelativeLayout bubble;

    private MapView mapView;

    public ColleagueOverlay(final Context context) {
        super(null);
        this.context = context;

        layoutInflator = LayoutInflater.from(context);
        bubble = (RelativeLayout) layoutInflator.inflate(R.layout.bubble,
                mapView, false);

        // Set up the bubble's close button
        ImageView bubbleClose = (ImageView) bubble
                .findViewById(R.id.bubbleclose);
        bubbleClose.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                Animation fadeOut = AnimationUtils.loadAnimation(context,
                        android.R.anim.fade_out);
                bubble.startAnimation(fadeOut);
                bubble.setVisibility(View.GONE);
            }
        });
    }

    /**
     * Adds a colleague to the overlay.
     * 
     * @param overlay
     *            Colleague overlay item to add to overlay.
     */
    public void addColleague(ColleagueOverlayItem overlay) {
        colleagues.add(overlay);
        populate();
    }

    public List<ColleagueOverlayItem> getColleagues() {
        return colleagues;
    }

    /** {@inheritDoc} */
    @Override
    protected ColleagueOverlayItem createItem(int i) {
        final ColleagueOverlayItem result = colleagues.get(i);
        final LayerDrawable marker = (LayerDrawable) context.getResources()
                .getDrawable(R.drawable.marker);

        Drawable photo = null;
        try {
            photo = Drawable.createFromStream(
                    context.getAssets().open(result.getColleague().getImg()), null);
        } catch (IOException e) {
            Log.e(this.getClass().getSimpleName(),
                    "Couldn't find photo: " + e.toString());
        }

        if (photo != null) {
            marker.setDrawableByLayerId(R.id.photo, photo);
            marker.setDrawableByLayerId(R.id.frame, context.getResources()
                    .getDrawable(R.drawable.blueframe));
        } else {
            // fetch from server
        }

        result.setMarker(boundCenterBottom(marker));

        return result;
    }

    /** {@inheritDoc} */
    @Override
    public int size() {
        return colleagues.size();
    }

    /** {@inheritDoc} */
    @Override
    protected boolean onTap(int index) {
        super.onTap(index);
        ColleagueOverlayItem item = colleagues.get(index);
        setFocus(item);
        displaySearchResultBubble(item);
        return true;
    }

    /** {@inheritDoc} */
    @Override
    public boolean onTap(GeoPoint p, MapView mapView) {
        this.mapView = mapView;
        super.onTap(p, mapView);
        // boolean tapped = super.onTap(p, mapView);
        // if (tapped)
        // mapView.getController().animateTo(p);
        return true;
    }

    private void displaySearchResultBubble(final ColleagueOverlayItem result) {
        Log.i(this.getClass().getSimpleName(),
                "Displaying colleague details...");
        mapView.removeView(bubble);
        bubble.setVisibility(View.GONE);

        ((TextView) bubble.findViewById(R.id.colleague_name)).setText(result
                .getTitle());
        ((TextView) bubble.findViewById(R.id.colleague_details)).setText(result
                .getSnippet());
        try {
            ((ImageView) bubble.findViewById(R.id.bubble_pic))
                    .setImageDrawable(Drawable.createFromStream(context
                            .getAssets().open(result.getColleague().getImg()), null));
        } catch (IOException e) {
            Log.e(this.getClass().getSimpleName(),
                    "Couldn't load profile pic in bubble", e);
        }

        // This is the important bit - set up a LayoutParams object for
        // positioning of the bubble. This will keep the bubble floating over
        // the GeoPoint result.getPoint() as you move the MapView around, but
        // you can also keep the view in the same place on the map using a
        // different LayoutParams constructor
        DisplayMetrics metrics = new DisplayMetrics();
        Display display = ((WindowManager) context
                .getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
        display.getMetrics(metrics);
        float screenDensity = metrics.density;
        Projection projection = mapView.getProjection();
        Point p = new Point();
        projection.toPixels(result.getPoint(), p);
        p.offset(0, (int) (-55 * screenDensity));
        GeoPoint target = projection.fromPixels(p.x, p.y);
        MapView.LayoutParams params = new MapView.LayoutParams(
                MapView.LayoutParams.WRAP_CONTENT,
                MapView.LayoutParams.WRAP_CONTENT, target,
                MapView.LayoutParams.BOTTOM_CENTER);
        bubble.setLayoutParams(params);
        mapView.addView(bubble);

        // Measure the bubble so it can be placed on the map
        // mapView.measure(
        // MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED),
        // MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));

        Runnable r = new Runnable() {
            public void run() {
                Animation fadeIn = AnimationUtils.loadAnimation(context,
                        android.R.anim.fade_in);
                bubble.setVisibility(View.VISIBLE);
                bubble.startAnimation(fadeIn);
            }
        };

        // This projection and offset finds us a new GeoPoint slightly below the
        // actual OverlayItem, which means the bubble will end up being centered
        // nicely when we tap on an Item.
        projection = mapView.getProjection();
        p = new Point();
        projection.toPixels(result.getPoint(), p);
        p.offset(0, -(bubble.getMeasuredHeight() / 2));
        target = projection.fromPixels(p.x, p.y);
        mapView.getController().animateTo(target, r);
    }

}
